package cn.demoncat.util.web;

import cn.demoncat.util.exception.IoRuntimeException;
import cn.demoncat.util.io.CloseUtil;
import cn.demoncat.util.lang.StringUtil;
import cn.demoncat.util.lang.constant.StringConstant;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 描述：读取资源（基于classpath）
 *
 * @author 延晓磊
 *
 * @since 2017年4月26日
 */
public final class ResourceUtil {

	
	private static final Logger LOG = LoggerFactory.getLogger(ResourceUtil.class);
 
	/**
	 * 获取文件的绝对路径
	 * 
	 * @param file	基于classpath的相对路径，如"resource/xx.txt"
	 * 
	 * @return {classpath绝对路径}/文件路径，文件不存在返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年5月7日
	 */
	public static String getPath(String file) {
		try {
			return ResourceUtils.getFile(StringConstant.CLASSPATH + StringUtil.removeStarts(file, StringConstant.SEPARATOR)).getAbsolutePath();
		} catch (FileNotFoundException e) {
			return null;
		}
	}
	
	/**
	 * 功能描述：读取Classpath下的资源文件
	 *
	 * @param path  基于classpath的相对路径，如"resource/xx.txt"
	 * @return  资源不存在返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年4月26日
	 */
	public static InputStream getIns(String path){
		//读取本地资源：基于Classpath 
		ClassPathResource classPathResource = new ClassPathResource(path);
		try {
			return classPathResource.getInputStream();
		} catch (IOException e) {
			// 文件不存在
			LOG.warn(errorMsgPath(path), e);
			return null;
		}
	}
	
	/**
	 * 
	 * 功能描述：读取Classpath下的资源文件
	 *
	 * @param path  基于classpath的相对路径，如"resource/xx.txt"
	 * @return  资源不存在返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年4月26日
	 */
	public static File getFile(String path){
		try {
			//读取本地资源：基于Classpath 
			return ResourceUtils.getFile(StringConstant.CLASSPATH + StringUtil.removeStarts(path, StringConstant.SEPARATOR));
		} catch (FileNotFoundException e) {
			// 文件不存在
			LOG.warn(errorMsgPath(path), e);
			return null;
		}
	}
	
	/**
	 * 功能描述：读取Classpath下的资源文件
	 *
	 * @param path  基于classpath的相对路径，如"resource/xx.txt"
	 * @return  资源不存在返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年4月26日
	 */
	public static Resource getResource(String path){
		//资源解析器
		ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		//读取本地资源：基于Classpath 
		Resource resource = resolver.getResource(StringConstant.CLASSPATH + StringUtil.removeStarts(path, StringConstant.SEPARATOR));
		//判断资源是否存在
		boolean exists = resource.exists();
		if(!exists){
			LOG.warn(errorMsgPath(path) + " error = 未找到");
			return null;
		} 
		return resource;
	}
	
	/**
	 * 功能描述：读取资源为String，忽略行首为 #的注释
	 *
	 * @param path  基于classpath的相对路径，如"resource/xx.txt"
	 * @return  资源不存在返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年4月26日
	 */
	public static String readStr(String path){
		//获取资源
		Resource resource = getResource(path);
		if(resource == null){
			return null;
		}
		//获取资源的读取流
		InputStream inputStream = null;
		BufferedReader br = null;
		try{
			inputStream = resource.getInputStream();
			br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
			//读取资源
			StringBuilder sb = new StringBuilder();
			String line;
			while((line = br.readLine()) != null){
				line = StringUtils.trimToEmpty(line);
				if (!line.equals(StringConstant.EMPTY) && ! line.startsWith(StringConstant.HASH)) {
					sb.append(line);
				}
			}
			return sb.toString();
		}catch(IOException e){
			throw new IoRuntimeException(errorMsgPath(path), e);
		}finally{
			CloseUtil.close(inputStream);
			CloseUtil.close(br);
		}
	}
	
	/**
	 * 功能描述：读取资源为List，忽略行首为 #的注释
	 *
	 * @param path  基于classpath的相对路径，如"resource/xx.txt"
	 * @return  资源不存在返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年4月26日
	 */
	public static List<String> readList(String path){
		//获取资源
		Resource resource = getResource(path);
		if(resource == null){
			return null;
		}
		//获取资源的读取流
		InputStream inputStream = null;
		BufferedReader br = null;
		try{
			inputStream = resource.getInputStream();
			br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
			//读取资源
			ArrayList<String> list = new ArrayList<>();
			String line;
			while((line = br.readLine()) != null){
				line = StringUtils.trimToEmpty(line);
				if (!line.equals(StringConstant.EMPTY) && ! line.startsWith(StringConstant.HASH)) {
					list.add(line);
				}
			}
			return list;
		}catch(IOException e){
			throw new IoRuntimeException(errorMsgPath(path), e);
		}finally{
			CloseUtil.close(inputStream);
			CloseUtil.close(br);
		}
	}
	
	/**
	 * 功能描述：读取资源为Set，忽略行首为 #的注释
	 *
	 * @param path  基于classpath的相对路径，如"resource/xx.txt"
	 * @return 资源不存在返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年4月26日
	 */
	public static Set<String> readSet(String path){
		//获取资源
		Resource resource = getResource(path);
		if(resource == null){
			return null;
		}
		//获取资源的读取流
		InputStream inputStream = null;
		BufferedReader br = null;
		try{
			inputStream = resource.getInputStream();
			br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
			//读取资源
			HashSet<String> set = new HashSet<>();
			String line;
			while((line = br.readLine()) != null){
				line = StringUtils.trimToEmpty(line);
				if (!line.equals(StringConstant.EMPTY) && ! line.startsWith(StringConstant.HASH)) {
					set.add(line);
				}
			}
			return set;
		}catch(IOException e){
			throw new IoRuntimeException(errorMsgPath(path), e);
		}finally{
			CloseUtil.close(inputStream);
			CloseUtil.close(br);
		}
	}
	
	/**
	 * 功能描述：读取资源为Map，忽略行首为 #的注释，KV以=分隔
	 *
	 * @param path  基于classpath的相对路径，如"resource/xx.txt"
	 * @return 资源不存在返回null
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年4月26日
	 */
	public static Map<String,String> readMap(String path){
		//获取资源
		Resource resource = getResource(path);
		if(resource == null){
			return null;
		}
		//获取资源的读取流
		InputStream inputStream = null;
		BufferedReader br = null;
		try{
			inputStream = resource.getInputStream();
			br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
			//读取资源
			HashMap<String,String> map = new HashMap<>();
			String line;
			String[] lines;
			while((line = br.readLine()) != null){
				line = StringUtils.trimToEmpty(line);
				if (!line.equals(StringConstant.EMPTY) && ! line.startsWith(StringConstant.HASH)) {
					lines = line.split(StringConstant.EQUAL);
					map.put(lines[0], lines.length > 1 ? lines[1] : null);
				}
			}
			return map;
		}catch(IOException e){
			throw new IoRuntimeException(errorMsgPath(path), e);
		}finally{
			CloseUtil.close(inputStream);
			CloseUtil.close(br);
		}
	}
	
	/**
	 * 错误消息：path
	 * 
	 * @param path
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年8月20日
	 */
	private static String errorMsgPath(String path) {
		return "读取资源失败：classpath = " + path;
	}
}
